package com.dog.basics.common.photooss.service.impl;



import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;
import com.dog.basics.common.photooss.properties.AliyunOSSProperties;
import com.dog.basics.common.photooss.service.PhotoOssUtil;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;

import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * @program: business
 *
 * @description: 阿里云  - oss 功能
 *
 * @author: Guo
 *
 * @create: 2020-02-06 15:46
 **/
@Log4j2
public class AliyunPhotoOssUtil implements PhotoOssUtil {

	/**
	 * 文件不存在
	 */
	private final String NO_SUCH_KEY = "NoSuchKey";
	/**
	 * 存储空间不存在
	 */
	private final String NO_SUCH_BUCKET = "NoSuchBucket";
	/**
	 * 配置信息
	 */
	private AliyunOSSProperties aliyunOSSProperties;
	public AliyunPhotoOssUtil(AliyunOSSProperties aliyunOSSProperties){
		log.info("初始化阿里云OSS");
		this.aliyunOSSProperties = aliyunOSSProperties;
	}

	/**
	 * 初始化
	 * @return
	 */
	private OSSClient initLoadOSSClient() {
		return new OSSClient(aliyunOSSProperties.getEndpoint(), aliyunOSSProperties.getAccessKeyId(), aliyunOSSProperties.getAccessKeySecret());

	}

	/**
	 * @功能描述: byte文件流上传
	 * @author He
	 * @date 2020/3/1 18:46
	 * @Param: [read, bucketName, storagePath, prefix]
	 * @Return: java.lang.String
	 */
	@Override
	public String uploadFile(byte[] read, String bucketName, String storagePath, String prefix) {
		return null;
	}

	/**
	 * @功能描述: 根据文件 inputstream 上传图片
	 * @author He
	 * @date 2020/2/29 19:45
	 * @Param: [inputStream, bucketName, storagePath, prefix]
	 * @Return: java.lang.String
	 */
	@Override
	public String uploadFile(InputStream inputStream, String bucketName, String storagePath, String prefix) {
		return null;
	}

	/**
	 * 上传文件到阿里云 OSS 服务器
	 *
	 * @param files
	 * @param bucketName
	 * @param storagePath
	 * @return
	 */
	@Override
	@SuppressWarnings("all")
	public List<String> uploadFile(MultipartFile[] files, String bucketName, String storagePath, String prefix) {
		OSSClient ossClient = initLoadOSSClient();
		//创建OSSClient实例
		List<String> fileIds = new ArrayList<>();
		try {
			for (MultipartFile file : files) {
				//创建一个唯一的文件名，类似于id，就是保存在OSS服务器上文件的文件名(自定义文件名)
				String fileName = file.getOriginalFilename();
				// 修改文件名称并保存文件
				String suffix = fileName.substring(fileName.lastIndexOf("."));
				fileName = RandomUtil.randomUUID() + suffix;
				InputStream inputStream = file.getInputStream();
				ObjectMetadata objectMetadata = new ObjectMetadata();
				//设置数据流里有多少个字节可以读取
				objectMetadata.setContentLength(inputStream.available());
				objectMetadata.setCacheControl("no-cache");
				objectMetadata.setHeader("Pragma", "no-cache");
				objectMetadata.setContentType(file.getContentType());
				objectMetadata.setContentDisposition("inline;filename=" + fileName);
				fileName = StrUtil.isNotBlank(storagePath) ? storagePath + "/" + fileName : fileName;
				//上传文件
				PutObjectResult result = ossClient.putObject(bucketName, fileName, inputStream, objectMetadata);
				log.info("Aliyun OSS AliyunOSSUtil.uploadFileToAliyunOSS,result:{}", result);
				fileIds.add(prefix + fileName);
			}
		} catch (IOException e) {
			log.error("Aliyun OSS AliyunOSSUtil.uploadFileToAliyunOSS fail,reason:{}", e);
		} finally {
			ossClient.shutdown();
		}
		return fileIds;
	}

	/**
	 * 上传文件到阿里云 OSS 服务器
	 *
	 * @param file
	 * @param bucketName
	 * @param storagePath
	 * @return
	 */
	@Override
	@SuppressWarnings("all")
	public String uploadFile(MultipartFile file, String bucketName, String storagePath, String prefix) {
		//创建OSSClient实例
		OSSClient ossClient = initLoadOSSClient();
		List<String> fileIds = new ArrayList<>();
		try {
				//创建一个唯一的文件名，类似于id，就是保存在OSS服务器上文件的文件名(自定义文件名)
				String fileName = file.getOriginalFilename();
				// 修改文件名称并保存文件
				String suffix = fileName.substring(fileName.lastIndexOf("."));
				fileName =StrUtil.format("{}/{}{}", DateUtil.format(DateUtil.date(), "yyyy/MM/dd"),RandomUtil.randomUUID(),suffix);;
				InputStream inputStream = file.getInputStream();
				ObjectMetadata objectMetadata = new ObjectMetadata();
				//设置数据流里有多少个字节可以读取
				objectMetadata.setContentLength(inputStream.available());
				objectMetadata.setCacheControl("no-cache");
				objectMetadata.setHeader("Pragma", "no-cache");
				objectMetadata.setContentType(file.getContentType());
				objectMetadata.setContentDisposition("inline;filename=" + fileName);
				fileName =  StrUtil.isNotBlank(storagePath) ? storagePath + "/" + fileName : fileName;
				//上传文件

 				PutObjectResult result = ossClient.putObject(bucketName, fileName, inputStream, objectMetadata);
				log.info("Aliyun OSS AliyunOSSUtil.uploadFileToAliyunOSS,result:{}", result);

				return prefix + fileName;
		} catch (IOException e) {
			log.error("Aliyun OSS AliyunOSSUtil.uploadFileToAliyunOSS fail,reason:{}", e);
		} finally {
			ossClient.shutdown();
		}
		return null;
	}


	/**
	 * 删除文件
	 *
	 * @param fileName
	 * @param bucketName
	 */
	@Override
	public void deleteFile(String fileName, String bucketName) {
		OSSClient ossClient = initLoadOSSClient();
		ossClient.deleteObject(bucketName, fileName);
		shutdown(ossClient);
	}

	/**
	 * 根据图片全路径删除就图片
	 *
	 * @param imgUrl     图片全路径
	 * @param bucketName 存储路径
	 */
	@Override
	public void delImg(String imgUrl, String bucketName) {
		if ( StrUtil.isEmpty(imgUrl)) {
			return;
		}
		//问号
		int index = imgUrl.indexOf('?');
		if (index != -1) {
			imgUrl = imgUrl.substring(0, index);
		}
		int slashIndex = imgUrl.lastIndexOf('/');
		String fileId = imgUrl.substring(slashIndex + 1);
		OSSClient ossClient = initLoadOSSClient();
		ossClient.deleteObject(bucketName, fileId);
		shutdown(ossClient);
	}

	/**
	 * 判断文件是否存在
	 *
	 * @param fileName   文件名称
	 * @param bucketName 文件储存空间名称
	 * @return true:存在,false:不存在
	 */
	@Override
	public boolean doesObjectExist(String fileName, String bucketName) {
		Validator.validateNotNull(fileName, "fileName can be not empty");
		Validator.validateNotNull(bucketName, "bucketName can be not empty");
		OSSClient ossClient = initLoadOSSClient();
		try {
			boolean found = ossClient.doesObjectExist(bucketName, fileName);
			return found;
		} finally {
			shutdown(ossClient);
		}

	}

	/**
	 * 复制文件
	 *
	 * @param fileName              源文件名称
	 * @param bucketName            源储存空间名称
	 * @param destinationBucketName 目标储存空间名称
	 * @param destinationObjectName 目标文件名称
	 */
	@Override
	@SneakyThrows
	public void ossCopyObject(String fileName, String bucketName, String destinationBucketName, String destinationObjectName) {
		Validator.validateNotNull(fileName, "fileName can be not empty");
		Validator.validateNotNull(bucketName, "bucketName can be not empty");
		Validator.validateNotNull(destinationBucketName, "destinationBucketName can be not empty");
		Validator.validateNotNull(destinationObjectName, "destinationObjectName can be not empty");
		// 拷贝文件。
		OSSClient ossClient = initLoadOSSClient();
		try {
			ossClient.copyObject(bucketName, fileName, destinationBucketName, destinationObjectName);
		} catch (OSSException oe) {
			log.error("errorCode:{},Message:{},requestID:{}", oe.getErrorCode(), oe.getMessage(), oe.getRequestId());
			if (oe.getErrorCode().equals(NO_SUCH_KEY)) {
				throw new Exception("文件不存在");
			} else if (oe.getErrorCode().equals(NO_SUCH_BUCKET)) {
				throw new Exception("存储空间不存在");
			} else {
				throw new Exception("拷贝失败");
			}
		} finally {
			shutdown(ossClient);
		}
	}

	/**
	 * 关闭oos
	 *
	 * @param ossClient ossClient
	 */
	private void shutdown(OSS ossClient) {
		ossClient.shutdown();
	}
}
